package com.sinosoft.ci.patch;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;

import com.sinosoft.ci.utils.FileSystemUtils;
import com.sinosoft.ci.utils.ZipUtils;

/**
 * 增量补丁生成器，用于从文件系统中抽取出补丁文件
 * 
 * @author 韩朝祥
 *
 */
public class IncrementPatchGenerator {
	private static final Logger logger = Logger.getLogger(IncrementPatchGenerator.class);
	// 提取补丁文件的目录
	private File baseDir;
	// 补丁文件存放的目录
	private File targetDir;
	
	public IncrementPatchGenerator(File baseDir, File targetDir){
		if(null == baseDir || targetDir == null){
			throw new NullPointerException("目录不能为 null！");
		}
		if(!baseDir.exists() || !baseDir.isDirectory()){
			throw new IllegalArgumentException(String.format("%s 不是一个合法目录！", baseDir.getAbsolutePath()));
		}
		
		this.baseDir = baseDir;
		this.targetDir = targetDir;
	}
	
	/**
	 * 根据文件条目进行补丁提取，条目是相对于 baseDir 的相对路径
	 * 
	 * @param patchPath 相对 targetDir 的相对目录
	 */
	public Map<String, ExtractResult> extractPatch(String[] fileEntrys, String patchPath){
		Map<String, ExtractResult> result = new HashMap<String, ExtractResult>();
		if(null == fileEntrys || fileEntrys.length < 1){
			return result;
		}
		File tempDir = getTempDir();

      result = extractPatchToDir(fileEntrys, tempDir);

      if(!targetDir.exists()){
			if(!targetDir.mkdirs()){
				throw new RuntimeException(String.format("目录 %s 创建失败！", targetDir.getAbsolutePath()));
			}
		}
		
		File destFile = new File(targetDir, patchPath);
		try{
			ZipUtils.zipDir(tempDir, destFile);
		}catch(IOException ex){
			logger.error(String.format("补丁文件 %s 压缩失败！", destFile.getAbsolutePath()), ex);
			throw new RuntimeException(String.format("补丁文件 %s 压缩失败！", destFile.getAbsolutePath()), ex);
		}finally{
			try{
				FileUtils.deleteDirectory(tempDir);
			}catch(IOException ex){
				ex.printStackTrace();
			}
		}
		
		return result;
	}

	public Map<String, ExtractResult> extractPatchToDir(String[] fileEntrys, File dir){
	  if(!dir.isDirectory()){
        throw new RuntimeException(String.format("路径 %s 不是目录", dir.getAbsolutePath()));
      }

      Map<String, ExtractResult> result = new HashMap<String, ExtractResult>();
      if(null == fileEntrys || fileEntrys.length < 1){
        return result;
      }

      for(String fileEntry : fileEntrys){
        File srcFile = new File(baseDir , fileEntry);
        if(!srcFile.exists()){
          logger.warn(srcFile.getAbsolutePath() + " 不存在！");
          result.put(fileEntry, ExtractResult.FAIL);
          continue;
        }

        if(srcFile.isDirectory()){
          logger.warn(srcFile.getAbsolutePath() + " 是目录，无法抽取！");
          result.put(fileEntry, ExtractResult.FAIL);
          continue;
        }

        ExtractResult r = ExtractResult.FAIL;
        File destFile = new File(dir,fileEntry);
        try{
          FileUtils.copyFile(srcFile, destFile);
          r = ExtractResult.SUCC;
        }catch(IOException ex){
          logger.warn(String.format("文件 %s 提取失败！", srcFile.getAbsolutePath()), ex);
          r = ExtractResult.FAIL;
        }

        result.put(fileEntry, r);
      }

      return result;
    }
	
	public enum ExtractResult{
		SUCC,// 提取成功
		FAIL// 提取失败
	}
	
	/**
	 * 获取临时文件目录
	 */
	private File getTempDir(){
		File tempDir = new File(FileSystemUtils.getSystemTempDir(),UUID.randomUUID().toString());
		try{
			if(tempDir.exists()){
				FileUtils.deleteDirectory(tempDir);
			}
			tempDir.mkdirs();
		}catch(IOException ex){
			logger.error(String.format("临时目录 %s 初始化失败！", tempDir.getAbsolutePath()),ex);
		}
		
		if(!tempDir.exists()){
			throw new RuntimeException(String.format("临时目录 %s 初始化失败！", tempDir.getAbsolutePath()));
		}
		
		return tempDir;
	}
}
